package com.syh.jn.scm.service.impl.supplier.finance;

import cn.redscarf.commons.wrapper.Restrictions;
import cn.redscarf.commons.wrapper.Wrapper;
import com.alibaba.dubbo.config.annotation.Service;
import com.syh.core.ddd.event.annotation.DomainEventHandle;
import com.syh.core.ddd.infrastructure.repository.AggregateRepository;
import com.syh.core.ddd.service.AbstractServiceImpl;
import com.syh.jn.scm.domain.operation.entity.supplier.OperaSupplier;
import com.syh.jn.scm.domain.operation.event.supplier.OperaSupplierEvent;
import com.syh.jn.scm.domain.supplier.entity.finance.IncomeBill;
import com.syh.jn.scm.domain.supplier.entity.finance.StatementAccountBill;
import com.syh.jn.scm.domain.supplier.event.IncomeBillEvent;
import com.syh.jn.scm.domain.supplier.event.finance.StatementAccountBillEvent;
import com.syh.jn.scm.domain.supplier.repository.finance.IncomeBillRepository;
import com.syh.jn.scm.dto.supplier.finance.IncomeBillMto;
import com.syh.jn.scm.dto.supplier.finance.IncomeBillSto;
import com.syh.jn.scm.dto.supplier.finance.IncomeBillVo;
import com.syh.jn.scm.dto.support.FilesDto;
import com.syh.jn.scm.service.api.supplier.finance.IncomeBillService;
import com.syh.jn.scm.service.api.supplier.finance.enums.IncomeBillEnum;
import com.syh.jn.scm.service.api.supplier.finance.enums.StatementAccountBillEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 收入单接口实现
 */
@Service
@Transactional
public class IncomeBillServiceImpl extends AbstractServiceImpl<IncomeBillSto, IncomeBillMto, IncomeBillVo, IncomeBill, Long> implements IncomeBillService {

  @Autowired
  private IncomeBillRepository incomeBillRepositoryImpl;

  @Override
  protected AggregateRepository<IncomeBill, Long> getAggregateRepository() {
    return incomeBillRepositoryImpl;
  }

  /**
   * 保存收入单
   *
   * @param sto
   * @return
   */
  @Override
  public Long save(IncomeBillSto sto) {
    IncomeBill bill = IncomeBill.createIncomeBill(sto);
    return incomeBillRepositoryImpl.add(bill);
  }

  /**
   * 更改收入单
   *
   * @param mto
   */
  @Override
  public void update(IncomeBillMto mto) {
    IncomeBill bill = incomeBillRepositoryImpl.getById(mto.getId());
    bill.modify(mto);
    incomeBillRepositoryImpl.update(bill);
  }

  /**
   * 删除收入单
   *
   * @param id
   */
  @Override
  public void delete(Long id) {
    IncomeBill bill = incomeBillRepositoryImpl.getById(id);
    bill.destroy();
    incomeBillRepositoryImpl.remove(bill);
  }

  /**
   * 确认
   *
   * @param id
   */
  @Override
  public void confirm(Long id) {
    IncomeBill bill = incomeBillRepositoryImpl.getById(id);
    bill.confirm();
    incomeBillRepositoryImpl.update(bill);

    //发送事件消息(生成应收付记录)
    //双方确认之后
    if (bill.getState().equals(IncomeBillEnum.CONFIRM.getStatus()) && bill.getConfirmState().equals(IncomeBillEnum.OTHERPARTY_CONFIRM.getStatus())) {
      this.publicEvent(IncomeBillEvent.buildStateConfirm(new Object[]{bill}));
    }
  }

  /**
   * 取消确认
   *
   * @param id
   */
  @Override
  public void cancelConfirm(Long id) {
    IncomeBill bill = incomeBillRepositoryImpl.getById(id);
    bill.cancelConfirm();
    incomeBillRepositoryImpl.update(bill);

    //当下游确认之后
    if (bill.getConfirmState().equals(IncomeBillEnum.OTHERPARTY_CONFIRM.getStatus())
            //或者客户类型是物流的时候
            || bill.getCustomerType() == 2) {
      Object[] obj = new Object[]{bill};
      //发送事件消息(生成应收付记录)
      this.publicEvent(IncomeBillEvent.buildStateUnConfirm(obj));
    }
  }

  /**
   * 取消
   *
   * @param id
   */
  @Override
  public void cancel(Long id) {
    IncomeBill bill = incomeBillRepositoryImpl.getById(id);
    bill.cancel();
    incomeBillRepositoryImpl.update(bill);

    /*Object[] obj = new Object[]{bill};
    //发送事件消息(生成应收付记录)
    this.publicEvent(IncomeBillEvent.buildIncomeBillStateEvent(obj));*/
  }

  /**
   * 上传单据图片
   *
   * @param dto
   */
  @Override
  public void upload(FilesDto dto) {
    IncomeBill bill = incomeBillRepositoryImpl.getById(dto.getId());
    bill.upload(dto);
    incomeBillRepositoryImpl.upload(bill);
  }

  /**
   * 消费者：监听对账单（生成对账单状态和对账单号）
   *
   * @param bill
   */
  @DomainEventHandle(StatementAccountBillEvent.STATEMENT_BILL_ACCOUNT_CREATED)
  protected void handleCostBillStateEvent(StatementAccountBill bill) {
    bill.getStatementAccountBillItems().forEach(billItem -> {
      if (billItem.getSourceType().equals(StatementAccountBillEnum.SOURCE_INCOME_BILL.getStatus())) {
        IncomeBill incomeBill = incomeBillRepositoryImpl.getById(billItem.getSourceId());
        incomeBill.generating(bill.getId());
        incomeBillRepositoryImpl.update(incomeBill);
      }
    });
  }

  /**
   * 消费者：监听对账单（生成对账单状态和对账单号）
   *
   * @param bill
   */
  @DomainEventHandle(StatementAccountBillEvent.STATEMENT_BILL_ACCOUNT_UPDATA)
  protected void handleStatementBillAccountUpdata(StatementAccountBill bill) {
    Wrapper wrapper = Wrapper.build();
    wrapper.append(Restrictions.eq("statementOfAccountId",bill.getId()));
    List<IncomeBill> incomeBills = incomeBillRepositoryImpl.getList(wrapper);
    incomeBills.forEach(incomeBill -> {
      incomeBill.cancelGenerating();
      incomeBillRepositoryImpl.update(incomeBill);
    });
    bill.getStatementAccountBillItems().forEach(billItem -> {
      if (billItem.getSourceType().equals(StatementAccountBillEnum.SOURCE_INCOME_BILL.getStatus())) {
        IncomeBill incomeBill = incomeBillRepositoryImpl.getById(billItem.getSourceId());
        incomeBill.generating(bill.getId());
        incomeBillRepositoryImpl.update(incomeBill);
      }
    });
  }

  /**
   * 消费者：监听对账单（删除对账单状态和对账单号）
   *
   * @param bill
   */
  @DomainEventHandle(StatementAccountBillEvent.STATEMENT_BILL_ACCOUNT_DESTROY)
  protected void handleCostBillRemoveStateEvent(StatementAccountBill bill) {
    bill.getStatementAccountBillItems().forEach(billItem -> {
      if (billItem.getSourceType().equals(StatementAccountBillEnum.SOURCE_INCOME_BILL.getStatus())) {
        IncomeBill incomeBill = incomeBillRepositoryImpl.getById(billItem.getSourceId());
        incomeBill.cancelGenerating();
        incomeBillRepositoryImpl.update(incomeBill);
      }
    });
  }

  /**
   * 消费者：监听服务商反开账（删除所有该服务商的收入单）
   */
  @DomainEventHandle(OperaSupplierEvent.SUPPLIER_REVERSAL_ACCOUNT)
  protected void handleSupplierReversalAccount(OperaSupplier supplier) {
    this.incomeBillRepositoryImpl.deleteByBusinessEntityId(supplier.getId());
  }
}
